package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.dubbo.api.VideoApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Video;
import com.tanhua.model.vo.CommentVo;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.VideoVo;
import com.tanhua.server.exceptions.BusinessException;
import com.tanhua.server.intercepror.UserHolder;
import com.tanhua.utils.Constants;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class SmallVideosService {

    @DubboReference
    private VideoApi videoApi;

    @Autowired
    private FastFileStorageClient client;

    @Autowired
    private FdfsWebServer webServer;

    @Autowired
    private OssTemplate ossTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired
    private MqMessageService mqMessageService;

    @DubboReference
    private CommentApi commentApi;

    /**
     * 视频上传
     *
     * @param videoThumbnail
     * @param videoFile
     */
//    @CacheEvict(value = "videos",allEntries = true)
    public void saveVideos(MultipartFile videoThumbnail, MultipartFile videoFile) throws IOException {
        //1.视频上传到fastDFS获取请求地址
        String filename = videoFile.getOriginalFilename();
        filename = filename.substring(filename.lastIndexOf(".") + 1);
        //上传到FastDFS，获取请求地址
        StorePath storePath = client.uploadFile(videoFile.getInputStream(), videoFile.getSize(), filename, null);//输入流，长度，后缀名，元数据
        String videoUrl = webServer.getWebServerUrl() + storePath.getFullPath();
        //2.图片上传到阿里云OSS，获取请求地址
        String picUrl = ossTemplate.upload(videoThumbnail.getOriginalFilename(), videoThumbnail.getInputStream());
        //3.创建Videos
        Video video = new Video();
        video.setCreated(System.currentTimeMillis());
        video.setUserId(UserHolder.getUserId());
        video.setText("爱意随风起，风止意难平");
        video.setPicUrl(picUrl);
        video.setVideoUrl(videoUrl);
        //4.调用API保存
        videoApi.save(video);
        //发送日志消息
//        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0301","log.video",v);
    }

    //查询视频列表
//    @Cacheable(value = "videos",key = "T(com.tanhua.server.intercepror.UserHolder).userId+" +
//            "'_'+#page+'_'+#pagesize")//使用全路径类名点方法
    public PageResult findVideo(Integer page, Integer pagesize) {
        //1.从Redis中查询条件数据（视频id的字符串）
        String key = Constants.VIDEOS_RECOMMEND + UserHolder.getUserId();
        String value = redisTemplate.opsForValue().get(key);
        //2.对查询的数据List进行判断
        List<Video> list = new ArrayList<>();
        if (!StringUtils.isEmpty(value)) {
            //3.有数据，根据video的id查询数据。返回List<Video>
            String[] vids = value.split(",");
            list = videoApi.findByIds(vids, page, pagesize);
        } else {
            //4.没数据，查询数据库中所有的数据
            list = videoApi.findAll(page, pagesize);
        }
        //5.将List<Video>转换成List<VideoVo>
        List<VideoVo> vos = new ArrayList<>();
        List<Long> ids = CollUtil.getFieldValues(list, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids);
        for (Video video : list) {
            Long userId = video.getUserId();
            UserInfo userInfo = map.get(userId);
            VideoVo vo = VideoVo.init(userInfo, video);

            String key1 = Constants.MOVEMENTS_INTERACT_KEY + video.getId().toHexString();
            String hashKey = Constants.VIDEO_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hasKey = redisTemplate.opsForHash().hasKey(key1, hashKey);
            if (hasKey) {
                vo.setHasLiked(1);
            }
            vos.add(vo);
        }
        //6.构造PageResult返回
        return new PageResult(page, pagesize, 0l, vos);
    }

    //点赞 点赞信息存在Comment中
    public Integer like(String videoId) {
        //mqMessageService.sendLogMessage(UserHolder.getUserId(), "0302", "log.video", videoId);
        //查询出用户信息
        Long userId = UserHolder.getUserId();
        Integer commentType = 1;//互动类型，1-点赞，2-评论，3-喜欢
        Integer type = 1; //标记是视频的点赞
        Boolean hasComment = commentApi.hasComment(videoId, userId, commentType);
        if (hasComment) {
            //存在用户已点赞
            throw new BusinessException(ErrorResult.likeError());
        }
        //3.未点赞，保存数据到Mongodb中
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));
        comment.setCommentType(commentType);
        comment.setUserId(userId); //点赞用id
        comment.setCreated(System.currentTimeMillis());
        //4.保存互动数据
        Integer count = commentApi.save(comment,type);
        //保存到Redis
        /**
         * 使用Redis的hash数据类型     key加上动态id  hashkey前缀加用户id
         */
        //操作hash
        String key = Constants.MOVEMENTS_INTERACT_KEY + videoId;
        String hashkye = Constants.VIDEO_LIKE_HASHKEY + userId;
        redisTemplate.opsForHash().put(key,hashkye,"1");
        return count;
    }

    //取消掉点赞
    public Integer dislike(String videoId) {
        //1.获取操作用户id
        Long userId = UserHolder.getUserId();
        Integer commentType = 1;
        Integer type = 1; //标记是视频的取消点赞
        //2.查询是否有点赞
        Boolean hasComment = commentApi.hasComment(videoId, userId, commentType);
        //3.进行判断，没有点赞操作抛出异常
        if (!hasComment) {
            throw new BusinessException(ErrorResult.disLikeError());
        }
        //3.1有点赞数据进行删除,返回最新的点赞总数
        Integer count = commentApi.delete(videoId, userId, commentType,type);
        //4.删除Redis中数据
        String key = Constants.MOVEMENTS_INTERACT_KEY + videoId;
        String hashKey = Constants.VIDEO_LIKE_HASHKEY+ userId;
        redisTemplate.opsForHash().delete(key, hashKey);//Redis中的key，需要删除的hashkey

        return count;
    }

    //查询评论列表
    public PageResult findComments(Integer page, Integer pagesize, String videoId) {
        Integer commentType = 2;//互动类型：评论
        List<Comment> list = commentApi.findComments(page, pagesize, commentType, videoId);
        //查询评论列表是否存在
        if (CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //提取所有发布人的id
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds);
        //查询所有发布人信息
        //遍历List<Comment>，一个Comment构造一个vo
        List<CommentVo> vos = new ArrayList<>();
        for (Comment comment : list) {
            //获取评论人的用户id
            Long userId = comment.getUserId();
            //根据key值userId查询出UserInfo
            UserInfo userInfo = map.get(userId);
            //把用户信息和互动表中的评论信息构造成一个vo
            CommentVo vo = CommentVo.init(userInfo, comment);
            vos.add(vo);
        }
        int count = list.size();
        return new PageResult(page, pagesize, Long.valueOf(count), vos);
    }

    //发布评论
    public void saveComment(String videoId, String content) {
        //判断用户是否冻结，查出用户
        Long userId = UserHolder.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);
        //String userStatus = userInfo.getUserStatus();
        if (userInfo.getUserStatus().equals("2")) {//用户状态,1为正常，2为冻结
            Integer freezingRange = userInfo.getFreezingRange();
            if (freezingRange == 2) {//冻结范围，1为冻结登录，2为冻结发言，3为冻结发布动态
                throw new BusinessException(ErrorResult.myError("该账号被冻结"));
            }
        }
        //构造Comment对象
        Integer commentType = 2;
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(videoId));
        comment.setCommentType(commentType);
        comment.setContent(content);
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        //调用API保存评论数据，返回评论总数量
        Integer count = commentApi.save(comment,1);
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0205","log.movement",videoId);

        System.out.println("评论总数量："+count);
    }
}
